package com.motu.monstercity.server.game.logic;

import com.motu.data.UserLoginDevice;
import com.motu.monstercity.module.common.redis.RedisKey;
import com.motu.monstercity.module.common.servermanager.ServerInfo;
import com.motu.monstercity.module.common.servermanager.ServerManager;
import com.motu.monstercity.module.common.utility.EventBusConstant;
import com.motu.monstercity.module.common.utility.ServerParam;
import com.motu.monstercity.protocol.Common.PBUserData;
import com.motu.monstercity.server.game.base.AllParam;
import com.motu.monstercity.server.game.base.CommonUtils;
import com.motu.monstercity.server.game.base.ProtoDataUtils;
import com.motu.monstercity.server.game.commondata.build.BuildConstant;
import com.motu.monstercity.server.game.commondata.fight.MonsterTideMain;
import com.motu.monstercity.server.game.commondata.iap.PrivilegeCardConstant;
import com.motu.monstercity.server.game.commondata.maintask.MainTaskConstant;
import com.motu.monstercity.server.game.commondata.maintask.TaskAchieve;
import com.motu.monstercity.server.game.commondata.system.SystemConstant;
import com.motu.monstercity.server.game.commondata.system.SystemOpen;
import com.motu.monstercity.server.game.log.LogType;
import com.motu.monstercity.server.game.log.ThinkingDataManager;
import com.motu.monstercity.server.game.userdata.*;
import com.motu.vertx.module.utility.base.ServerConfig;
import com.motu.vertx.module.utility.main.MainService;
import com.motu.vertx.module.utility.model.EntityManager;
import com.motu.vertx.module.utility.redis.RedisTools;
import com.motu.vertx.module.utility.toolset.TimeUtils;
import com.motu.vertx.module.utility.toolset.Tool;
import io.vertx.core.Future;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

public class SystemManager {
    // 通知gameinit verticle 处理相关业务
    public static void noticeGameInit(JsonObject message) {
        String ebName = EventBusConstant.getAddress(EventBusConstant.GAME_INIT);
        EventBus eventBus = MainService.getVertx().eventBus();
        eventBus.send(ebName, message);
    }

	/**
	 * 处理玩家首次登录逻辑
	 * @param pbUserData 下发给客户端的用户数据
	 * @param userInfo 用户信息
	 * @param userExtInfo 用户扩展信息
	 * @param userLoginDevice 用户登录设备信息
	 */
	public static void doFirstLogin(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userExtInfo, UserLoginDevice userLoginDevice,String isOldRole) {

		//数数注册事件
		ThinkingDataManager.pushRegisterEvent(userInfo,userLoginDevice,isOldRole);

		// 新角色注册时赠送的道具
		RewardManager.addReward(userInfo, CommonUtils.takeReawrdItemFromStr(AllParam.NEW_ROLE_REWARD), pbUserData, LogType.SYSTEM_REWARD);

		//  玩家初始默认头像 默认使用第一个
		for (int i = 0; i< AllParam.CARD_ICON.length; i++) {
			RewardManager.addReward(userInfo, AllParam.CARD_ICON[i], 1, pbUserData, LogType.SYSTEM_REWARD);
		}
		userInfo.putIcon(AllParam.CARD_ICON[0] + "");//

		//  玩家初始默认头像框 默认使用第一个
		for (int i = 0; i< AllParam.CARD_ICON_FRAME.length; i++) {
			RewardManager.addReward(userInfo, AllParam.CARD_ICON_FRAME[i], 1, pbUserData, LogType.SYSTEM_REWARD);
		}
		userInfo.putIconFrame(AllParam.CARD_ICON_FRAME[0]);

		//  初始获得的聊天气泡 默认使用第一个
		for (int i = 0; i< AllParam.CARD_BUBBLE.length; i++) {
			RewardManager.addReward(userInfo, AllParam.CARD_BUBBLE[i], 1, pbUserData, LogType.SYSTEM_REWARD);
		}
		userInfo.putBubbleId(AllParam.CARD_BUBBLE[0]);



		userExtInfo.putRyDeviceType(userLoginDevice.getDeviceType());
		userExtInfo.putDeviceId(userLoginDevice.getDeviceId());
		userExtInfo.putIdfa(userLoginDevice.getIdfa());
		userExtInfo.putIdfv(userLoginDevice.getIdfv());
		userExtInfo.putImei(userLoginDevice.getImei());
		userExtInfo.putAndroidId(userLoginDevice.getAndroidId());
		userExtInfo.putRyOs(userLoginDevice.getRyos());
	}

	/**
	 * 处理玩家每次登录逻辑
	 * @param pbUserData 下发给客户端的用户数据
	 * @param userInfo 用户信息
	 * @param userExtInfo 用户扩展信息
	 * @param userLoginDevice 用户登录设备信息
	 */
	public static void doLogin(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userExtInfo, UserLoginDevice userLoginDevice) {

		/** 处理玩家每日第一次登录逻辑 **/
		boolean isFirstLoginToday = !TimeUtils.isToday(userInfo.getLoginTime());// 是否今天第一次登录
		if (isFirstLoginToday){
			doTodayFirstLogin(pbUserData, userInfo, userExtInfo, userLoginDevice);
		}

		/** 处理玩家每次登录逻辑 **/

		// 更新登录日志中的登录次数
		long curTime = TimeUtils.getCurTime();
		long loginDate = TimeUtils.getStartTimeOfDay(curTime);
		GameUser.updateUserLoginCount(userInfo.getId(), loginDate);

		// 更新登录时间和登录次数
		userInfo.putLoginTime(curTime);
		userExtInfo.addLoginCount(1);
		userExtInfo.putIp(userLoginDevice.getIp());

	}

	/**
	 * 处理玩家每日第一次登录逻辑（如果是每次登录都要执行的就不是放这里）
	 * @param pbUserData 下发给客户端的用户数据
	 * @param userInfo 用户信息
	 * @param userExtInfo 用户扩展信息
	 * @param userLoginDevice 用户登录设备信息
	 */
	private static void doTodayFirstLogin(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userExtInfo, UserLoginDevice userLoginDevice) {
		// 更新登录天数
		userExtInfo.addLoginDayCount(1);
		MainTaskManager.updateTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_242, userExtInfo.getLoginDayCount());// 更新主线任务,成就,日常任务的进度
		RankActManager.updateTaskProgress(pbUserData, userInfo, MainTaskConstant.TASK_TYPE_242, userExtInfo.getLoginDayCount());


		// 记录每日首次登录日志
		long curTime = TimeUtils.getCurTime();
		long loginDate = TimeUtils.getStartTimeOfDay(curTime);
		GameUser.addUserLoginLog(userInfo.getServerId(), userExtInfo.getId(), userInfo.getLevel(), userInfo.getVip(), userLoginDevice.getPlatform(), loginDate);

	}

	/**
	 * 登录时处理用户的活动数据
	 * @param pbUserData
	 * @param userInfo
	 * @param userExtInfo
	 */
	public static void doUserActData(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userExtInfo) {
//        ActDaysManager.updateTask(userInfo, ActTask.TASK_TYPE_LOGIN, 1); // 七天乐登录
//        ActDaysManager.closeAct(userInfo); // 七天乐结算
//        ActManager.checkActIapGiftPush(userInfo, userExtInfo); // 活动推送礼包
	}

    /**
     * system_init 接口加载用户数据
     */
    public static void loadInitUserData(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userExtInfo, boolean isNoLoadAll) {
        long userId = userInfo.getId();
        ProtoDataUtils.updatePBUserData(pbUserData, userInfo, true);
        ProtoDataUtils.updatePBUserData(pbUserData, userExtInfo, true);
        ActManager.loadActInfo(pbUserData, userInfo, userExtInfo);
        ActManager.loadUserActInfo(pbUserData, userInfo, userExtInfo);

		RankActManager.loadActInfo(pbUserData, userInfo);

        UserAffair userAffair = GameUser.getUserAffair(userId);
        ProtoDataUtils.updatePBUserData(pbUserData, userAffair, true);

		UserAdvideo userAdvideo = GameUser.getUserAdvideo(userId);
		ProtoDataUtils.updatePBUserData(pbUserData, userAdvideo, true);

        BagManager.loadInitBagUserData(pbUserData, userInfo);// 初始化 下发背包模块的用户数据
        FightManager.loadInitFightUserData(pbUserData, userInfo);// 下发站点副本模块的用户数据

        FloristManager.initFlorist(userInfo); // 初始化花店数据
        IapManager.loadInitIapUserData(pbUserData, userInfo);//下发充值付费
        MainTaskManager.loadInitUserData(pbUserData, userInfo);// 下发主线任务相关的用户数据

		ChildManager.loadInitChildUserData(pbUserData, userInfo);// 初始化 下发子嗣模块的用户数据

		DatingManager.loadInitDatingUserData(pbUserData, userInfo);// 初始化下发约会数据

		CaveManager.loadInitCaveUserData(pbUserData, userInfo);// 初始化，下发怪兽洞窟的用户数据

		UnionManager.loadInitUnionUserData(pbUserData, userInfo);// 初始化，下发联盟的用户数据

		BuddyManager.loadInitBuddyUserData(pbUserData, userInfo);// 初始化，下发好友模块的用户数据

		UnionScuffleManager.loadTimeInfo(pbUserData); // 初始化，下发联盟乱斗时间数据


		//  战力,城市收益重算
		UserPower userPower = GameUser.getUserPower(userId);
		List<UserPartner> partnerList = new ArrayList<>();// 干员列表
		List<UserWeapon> weaponList = new ArrayList<>();// 武器列表
		List<UserBuild> buildList = new ArrayList<>();// 建筑列表
		List<UserSecretary> secretaryList = new ArrayList<>();// 秘书列表
		PartnerManager.loadInitPartnerUserData(pbUserData, userInfo, partnerList, weaponList);// 下发干员模块的用户数据
		BuildManager.loadInitBuildUserData(pbUserData, userInfo, buildList, isNoLoadAll);// 下发建筑模块的用户数据
		SecretaryManager.loadInitSecretaryData(pbUserData, userInfo, secretaryList);// 下发秘书模块的用户数据

		EventManager.initUserData(userExtInfo, pbUserData);
		WorldManager.loadInitWorldUserData(pbUserData, userInfo);// 初始化下发大世界行军模块的用户数据

		GameUser.handleRecountSkillEffect(pbUserData, userId, partnerList, secretaryList);// 重算干员，秘书技能在各个模块的总加成值

		if (isRecount(userId)) {// 是否需要重算该玩家的userpower,干员，和城市收益信息
			GameUser.refreshUserPower(userInfo, userPower, userAffair, partnerList, secretaryList, buildList);// 重算userpower的字段power_add_title_per，power_add_world_cv等字段
			GameUser.reCountPower(pbUserData, userInfo, userPower, partnerList, secretaryList);// 登录时重算玩家的战力
			GameUser.reCountEarn(pbUserData, userInfo, userPower, buildList);// 登录时重算玩家的城市收益
			userPower.update();
		}

		ProtoDataUtils.updatePBUserData(pbUserData, userPower, true);
    }

    /**
     * system_init 接口加载系统参数数据
     */
    public static void loadInitSystemData(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userextInfo) {
		//服务器当前时间
		pbUserData.getSystemBuilder().setSvrTime(TimeUtils.getCurTime());

		pbUserData.getSystemBuilder().setPayMoneyRegion(ServerParam.PAY_MONEY_REGION);

		// 服务器类型（0-正式服 1-测试服 2-评审服）
		pbUserData.getSystemBuilder().setDebugType(ServerConfig.getDebugType());

		// 下发参数配置
        JsonObject paramsClient = GameDataManager.getParamsClientObject();
        if (!paramsClient.isEmpty()) {
            pbUserData.getSystemBuilder().setParams(paramsClient.toString());
        }

        //下发客户端功能开关配置
        pbUserData.getSystemBuilder().addAllFunctionList(GameDataManager.getFunctionClientList(userInfo.getServerId(), userextInfo.getPlatform()));

		// 时区
		Calendar calendar = new GregorianCalendar();
		pbUserData.getSystemBuilder().setTimezone(calendar.getTimeZone().getOffset(System.currentTimeMillis()) / 1000);

		// 开服时间
		ServerInfo serverinfo = ServerManager.getServerInfo(userInfo.getServerId());
		if (serverinfo != null) {
			pbUserData.getSystemBuilder().setServerStartTime(serverinfo.getStartTime());
		}

		// 服务器当天24点时间
		pbUserData.getSystemBuilder().setDailyEndTime(TimeUtils.getStartTimeOfDay(TimeUtils.getCurTime()) + TimeUtils.DAY);

		// systemOpen配置
		pbUserData.getSystemBuilder().addAllSystemOpenList(GameDataManager.getPBSystemOpenList());

	}

	/**
	 * system_init 接口加载活动相关的数据，如比较简单一次性的固定活动，后台配置的活动，比较复杂的活动，循环活动等
	 */
	public static void loadInitActData(PBUserData.Builder pbUserData, UserInfo userInfo, UserExtInfo userextInfo) {
		OnceActManager.loadInitUserData(pbUserData, userInfo);// 初始化，玩家init接口下发一次性固定活动的用户数据

		List<UserAct> userActList = ActDaysManager.getUserMotifActList(userInfo, false);
		for (UserAct userAct : userActList) {
			ProtoDataUtils.updatePBUserData(pbUserData, userAct);
		}
	}

		/**
         * 通知各进程重载acw_word表
         */
    public static void noticReloadActWord() {
        //todo
    }

	// 校验系统模块是否解锁,有些模块的用户数据需要初始化,并下发给客户端
	public static void checkSystemModelOpen(PBUserData.Builder pbUserData, UserInfo userInfo, UserAffair userAffair, UserStage userStage, int systemModleId) {
		if (checkModuleOpen(userInfo, userAffair, userStage, systemModleId)) {// 已解锁
			long userId = userInfo.getId();
			switch (systemModleId) {
				case SystemConstant.SYSTEM_MODULE_ID_STAGE_GUARD_REWARD:
					if (!userStage.isGuardRewardOpen()) {
						userStage.putGuardRewardTime(TimeUtils.getCurTime());
						userStage.putGuardRewardRandomTime(TimeUtils.getCurTime());
						userStage.putGuardRewardLastTime(TimeUtils.getCurTime());
						break;
					}
				case SystemConstant.SYSTEM_MODULE_ID_PATROL:
					userInfo.recoverEnergy();
					break;
			}
		}
	}


	/**
	 * 尝试解锁系统，传入玩家信息和系统ID
	 * @param userInfo
	 * @param moduleId
	 * @return
	 */
	public static void tryUnlockSystem(PBUserData.Builder pbUserData,UserInfo userInfo, int moduleId){
		UserAffair userAffair = GameUser.getUserAffair(userInfo.getId());
		UserStage userStage = FightManager.getUserStage(userInfo.getId());
		if (!checkModuleOpen(userInfo, userAffair, userStage, moduleId)) {
			return;
		}
		long userId = userInfo.getId();
		switch (moduleId) {
			case SystemConstant.SYSTEM_MODULE_ID_DISCOUNT_GIFT: // 解锁折扣礼包后触发尝试推送 TODO 可以尝试在升级的时候去做推送操作。需要优化成通用的调用
				UserActDiscountGift discountGift = OnceActManager.tryTriggerDiscountGift(userId);
				ProtoDataUtils.updatePBUserData(pbUserData, discountGift, true);
				break;
		}
	}

	public static boolean checkModuleOpen(UserInfo userInfo, int moduleId){
		UserAffair userAffair = GameUser.getUserAffair(userInfo.getId());
		UserStage userStage = FightManager.getUserStage(userInfo.getId());
		return checkModuleOpen(userInfo, userAffair, userStage, moduleId);
	}


	/**
	 * 校验系统模块是否开启
	 * @param userInfo
	 * @param moduleId 模块id 配置在SystemConstant
	 * @return
	 */
	public static boolean checkModuleOpen(UserInfo userInfo, UserAffair userAffair, UserStage userStage, int moduleId){
		SystemOpen systemOpen = GameDataManager.getSystemOpen(moduleId);
		if (systemOpen == null) {
			return true;// 未配置的默认开启
		}

		JsonArray jsonArray = userAffair.getSystemOpenArray();
		if (Tool.isInList(jsonArray, moduleId)) {
			return true;// 已解锁
		}

		long userId = userInfo.getId();
		if (systemOpen.getNeedBuild() > 0) {
			UserBuild userBuild = BuildManager.getUserBuild(userId, systemOpen.getNeedBuild());// 建筑这个是必须条件
			if (userBuild == null || !userBuild.isPlace())  {
				return false;// 未获得或是未放置,则表示未解锁
			}
		}

		// 条件1.或是条件2只要有一个达成就解锁模块
		boolean result = false;
		boolean flag1 = checkModuleOpenUnlock(userInfo, userStage, systemOpen.getUnlockType1(), systemOpen.getUnlockParam1());
		if (systemOpen.getUnlockType1() > 0 && systemOpen.getUnlockParam1() > 0 && flag1) {
			result = true;
		}
		boolean flag2 = checkModuleOpenUnlock(userInfo, userStage, systemOpen.getUnlockType2(), systemOpen.getUnlockParam2());
		if (systemOpen.getUnlockType2() > 0 && systemOpen.getUnlockParam2() > 0 && flag2) {
			result = true;
		}

		if (result) {
			jsonArray.add(moduleId);
			userAffair.putSystemOpen(jsonArray.toString());
			userAffair.update();// 记录下来避免重复计算
		}

		return result;
	}

	// 某个解锁类型是否达成,unlock_param配置=0则表示直接达成
	private static boolean checkModuleOpenUnlock(UserInfo userInfo, UserStage userStage, int unlockType, int value) {
		if (unlockType == 0 || value == 0) {
			return true;
		}
		long userId = userInfo.getId();
		switch (unlockType) {
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_1:// 玩家等级（市政中心等级）达到等级解锁
				return userInfo.getLevel() >= value;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_2:// 壁外探索通过第X章解锁
				return userStage.getMapId() > value;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_3:// 主线任务X的任务条件（根据任务ID取其任务子类和要求）达成后解锁
				TaskAchieve taskAchieve = MainTaskManager.getTaskAchieve(value);
				if (taskAchieve != null && MainTaskManager.isTaskComplete(userId, taskAchieve)) {
					return true;
				}
				break;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_4:// VIP达到X级解锁
				return userInfo.getVip() >= value;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_5:// 获得过月卡后解锁,且月卡未过期
				UserPrivilegeCard userPrivilegeCard = IapManager.getUserPrivilegeCard(userId, PrivilegeCardConstant.PRIVILEAGE_CARD_TYPE_1);
				if (userPrivilegeCard != null && !userPrivilegeCard.isExpired()) {
					return true;
				}
				break;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_6:// 获得过终身卡后解锁
				UserPrivilegeCard userPrivilegeCard2 = IapManager.getUserPrivilegeCard(userId, PrivilegeCardConstant.PRIVILEAGE_CARD_TYPE_2);
				if (userPrivilegeCard2 != null && !userPrivilegeCard2.isExpired()) {
					return true;
				}
				break;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_7:// 获得过武器后解锁,武器数量
				JsonArray jsonArray = EntityManager.getEntityKeyList(UserWeapon.class, userId);
				return jsonArray.size() >= value;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_8:// 获得过后代后解锁,子嗣数量
				UserChildInfo userChildInfo = ChildManager.getUserChildInfo(userId);
				return userChildInfo.getChildNum() >= value;
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_9:// 系统模块的解锁条件类型 世界远征的雷达等级
				UserBuild userBuild = BuildManager.getUserBuild(userId, BuildConstant.BUILD_ID_RADAR);
				if (userBuild != null && userBuild.getLevel() >= value) {
					return true;
				} else {
					return false;
				}
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_10:// 系统模块的解锁条件类型 壁外探索通过第1章的第X关
				if (userStage.getMapId() > 1 || userStage.getStageId() >= value) {
					return true;
				} else {
					return false;
				}
			case SystemConstant.SYSTEM_MOUDLE_OPEN_TYPE_11:// 系统模块的解锁条件类型 建造@餐厅 restaurant_main表格中的id 配置在value字段
				UserRestaurantRoom userRestaurantRoom = RestaurantManager.getUserRestaurantRoom(userId, value);
				if (userRestaurantRoom != null) {
					return true;
				} else {
					return false;
				}
		}
		return false;
	}

	/***
	 * 根据设备Id判断一个新建的角色是否为滚服角色
	 * @param deviceid
	 * @return
	 */
    public static String isOldRole(String deviceid) {
		//redis校验设备是否注册过
		deviceid.replace(':', '_');//rediskey不能使用冒号，此处替换成下划线
		String hashKey = RedisKey.getRegisterDeviceidKey(deviceid);
		String hashValue = Future.await(RedisTools.get(hashKey));
		if (!Tool.isEmpty(hashValue)) {
			return hashValue;
		} else {
			RedisTools.set(hashKey, "" + TimeUtils.getCurTime());
			return "";
		}
	}

	// 是否需要重算该玩家的userpower,干员，和城市收益信息
	public static boolean isRecount(long userId) {
		if (AllParam.IS_RECOUNT_CLOSE == 0) {
			return true;
		}
		if (Tool.isInList(AllParam.RECOUNT_USERID_LIST, userId)) {
			return true;
		}
		return false;
	}
}
